<template>
  <div class="rich-text-editor-wrapper">
    <div class="util-list-wrapper">
      <ul class="util-list">
        <li v-for="(util, idx) in utilIcons" 
        :key="idx" @mousedown.prevent="clickIcon(util)"
        @mouseenter="showChoices(util)"
        @mouseleave="fadeChoices(util)">
          <h2 class="iconfont" :class="util.iconClass"></h2>
          <h3>{{util.showName}}</h3>

          <input type="file" class="image-upload" v-if="util.name==='imageFill'"
          @change="addImg($event)" title="">

          <ul v-if="util.choices"  class="util-choices" :class="{fadeOut: !util.showChoices}">
            <li v-for="(choice,idx) in util.choices" :key="idx"
            @click="clickChoice(util, choice)">
              {{ choice.cover }}
            </li>
          </ul>
        </li>
      </ul>
    </div>

    <pop-up class="insert-link-popup" :fadeIn="showInsertLink">
      <insert-link class="insert-link" @exit="showInsertLink = false"
      @submit="insertLink"></insert-link>
    </pop-up>

    <div class="display" ref="display">
      <input class="title" placeholder="请输入标题" v-model="article.title"/>

      <iframe :src="$routeBaseURL + '/RTF.html'" ref="main"
      width="100%" height="100%"
      frameborder="0" class="main"></iframe>
    </div>
  </div>
</template>

<script>
import utils from '@/assets/js/utils';

import PopUp from '@/components/utils/PopUp.vue';
import InsertLink from './InsertLink.vue'

  export default {
    components: {
      PopUp,
      InsertLink
    },
    emits: ['store'],
    data() {
      return {
        utilIcons: [
          {
            iconClass: 'icon-unorderedlist',
            name: 'unorderedlist',
            showName: '无序列表',
            tag: {
              name: 'ul > li',
              type: 'block'
            }
          },
          {
            iconClass: 'icon-orderedlist',
            name: 'orderedlist',
            showName: '有序列表',
            tag: {
              name: 'ol > li',
              type: 'block'
            }
          },
          {
            iconClass: 'icon-bold',
            name: 'bold',
            showName: '加粗',
            tag: {
              name: 'b',
              type: 'inline'
            }
          },
          {
            iconClass: 'icon-title',
            name: 'title',
            showName: '标题',
            tag: {
              name: 'h1 > p',
              type: 'block'
            },
            choices: [
              {
                cover: '一级标题',
                tag: {
                  name: 'h1 > p'
                }
              },
              {
                cover: '二级标题',
                tag: {
                  name: 'h2 > p'
                }
              }
            ],
            showChoices: false
          },
          {
            iconClass: 'icon-font-colors',
            name: 'fontColors',
            showName: '颜色',
            tag: {
              name: 'span',
              type: 'inline'
            },
            choices: [
              {
                cover: '黑色',
                tag: {
                  style: {
                    color: 'black'
                  }
                }
              },
              {
                cover: '红色',
                tag: {
                  style: {
                    color: 'red'
                  }
                }
              },
              {
                cover: '黄色',
                tag: {
                  style: {
                    color: '#ffcc11'
                  }
                }
              },
              {
                cover: '蓝色',
                tag: {
                  style: {
                    color: 'blue'
                  }
                }
              }
            ],
            showChoices: false
          },
          {
            iconClass: 'icon-image-fill',
            name: 'imageFill',
            showName: '图片',
            tag: {
              name: 'img',
              type: 'block'
            }
          },
          {
            iconClass: 'icon-quote',
            name: 'blockquote',
            showName: '引用',
            tag: {
              name: 'blockquote > p',
              type: 'block'
            }
          },
          {
            iconClass: 'icon-code',
            name: 'code',
            showName: '代码段',
            tag: {
              name: 'code > p',
              type: 'block'
            }
          },
          {
            iconClass: 'icon-link',
            name: 'link',
            showName: '链接',
            tag: {
              name: 'a',
              type: 'inline'
            }
          }
        ],
        article: {
          title: '',
          content: '',
          text: '',
        },
        showInsertLink: false,
        iframeWindowState: 0,
      }
    },
    methods: {
      addTag(tag) {
        let main = this.$refs.main;
        let win = main.contentWindow;
        win.postMessage(JSON.stringify({tag, type: 'addTag'}));
      },
      clickIcon(util) {
        if(util.name === 'imageFill') return;
        if(util.name === 'link') {
          this.showInsertLink = true;
          return;
        }
        if(!util.choices) {
          this.addTag(util.tag);
          return;
        }
      },
      addImg(e) {
        let img = e.target.files[0];
        this.$compressImage(img).then(file => {
          let reader = new FileReader();
          reader.onload = () => {
            let url = reader.result;
            let tag = {
              name: 'img',
              type: 'block',
              url
            };
            this.addTag(tag);
            e.target.value = "";
          };
          reader.readAsDataURL(file);
        })
      },
      insertLink(link) {
        console.log('inser link', link);
        this.addTag({
          name: 'a',
          type: 'inline',
          ...link
        });
        this.showInsertLink = false;
      },
      clickChoice(util, choice) {
        let tag = JSON.parse(JSON.stringify(util.tag));
        if(!tag.style) tag.style = {};
        let mergeTag = choice.tag;
        if(mergeTag.name) tag.name = mergeTag.name;
        if(mergeTag.style) {
          Object.keys(mergeTag.style).forEach(key => {
            tag.style[key] = mergeTag.style[key];
          })
        }
        this.addTag(tag);
      },
      getArticle() {
        return new Promise((resolve, reject) => {
          let listener = (event) => {
            try{
              JSON.parse(event.data);
            } catch {
              return;
            }
            let operation = JSON.parse(event.data);
            if(operation.type === 'sendArticle') {
              this.article.content = operation.content;
              this.article.text = operation.text;
              resolve(JSON.parse(JSON.stringify(this.article)));
            }
            window.removeEventListener("message", listener);
          }
          window.addEventListener('message', listener);
          this.$refs.main.contentWindow.postMessage(JSON.stringify({type: 'getArticle'}));
        })
      },
      getRawArticle() {
        return new Promise((resolve, reject) => {
          let listener = (event) => {
            try{
              JSON.parse(event.data);
            } catch {
              return;
            }
            let operation = JSON.parse(event.data);
            if(operation.type === 'sendRawArticle') {
              this.article.content = operation.content;
              this.article.text = operation.text;
              resolve(JSON.parse(JSON.stringify(this.article)));
            }
            window.removeEventListener("message", listener);
          }
          window.addEventListener('message', listener);
          this.$refs.main.contentWindow.postMessage(JSON.stringify({type: 'getRawArticle'}));
        })
      },
      showChoices(util) {
        if(util.choices) {
          util.showChoices = true;
        }
      },
      fadeChoices(util) {
        if(util.choices) {
          util.showChoices = false;
        }
      },
      fillDraft(draft) {
        let win = this.$refs.main.contentWindow;
        if(this.iframeWindowState) {
          win.postMessage(JSON.stringify({
            type: 'fillDraft',
            draft: draft.content
          }));
        } else {
          win.onload = () => {
            win.postMessage(JSON.stringify({
              type: 'fillDraft',
              draft: draft.content
            }));
          }
        }
        this.article.title = draft.title;
      },
      clear() {
        this.article.title = '';
        this.$refs.main.contentWindow.postMessage(JSON.stringify({
          type: 'clear'
        }));
      }
    },
    mounted () {
      this.$refs.main.contentWindow.onload = () => {
        this.iframeWindowState = 1;
      }

      this.utilIcons.forEach(el => {
        el.methodName = 'add' + el.name[0].toUpperCase() + el.name.slice(1);
      });

      window.addEventListener('message', event => {
        let dataStr = event.data, data = null;
        try {
          data = JSON.parse(dataStr);
          if(data.type === 'store') {
            this.$emit('store');
          } else if(data.type === 'changeRTFHeight') {
            let main = document.querySelector(".display .main");
            main.style.height = `${data.height}px`;
          }
        } catch {
        };
      });

      document.addEventListener("keydown", (event) => {
        if(event.ctrlKey && event.key === 's') {
          event.preventDefault();
          this.$emit('store');
        }
      });
    },
  }
</script>

<style lang="less" scoped>
@iw: var(--richTextEditorWidth);

.rich-text-editor-wrapper {
  box-sizing: border-box;
  position: relative;
  padding-top: var(--richTextEditorUtilHeight);
  --richTextEditorUtilHeight: calc(var(--topNavHeight) * 0.8);

  .util-list-wrapper {
    position: fixed;
    width: 100vw;
    top: var(--topNavHeight);
    z-index: 1;
    background-color: var(--bgColor);
    border-bottom: 1px solid var(--gray);
    border-top: 1px solid var(--gray);

    .util-list {
      margin: 0 auto;
      display: flex;
      justify-content: space-between;
      align-items: center;
      width: var(--outerWidth);
      height: var(--richTextEditorUtilHeight);
      padding: calc(var(--richTextEditorUtilHeight) / 10);

      > li {
        position: relative;

        box-sizing: border-box;
        height: var(--richTextEditorUtilHeight);
        --h1: calc(var(--richTextEditorUtilHeight) * 0.5);
        --h2: calc(var(--richTextEditorUtilHeight) - var(--h1));
        width: 70px;
        padding: 2px 0;

        border-radius: 3px;
        flex-basis: 1;
        text-align: center;

        .util-choices {
          background-color: white;
          border-radius: 5px;
          width: 120%;
          overflow: hidden;

          position: absolute;
          top: 100%;
          left: -10%;

          transition: .2s;

          > li {
            height: 30px;
            line-height: 30px;
            text-align: center;
            font-size: 12px;

            &:hover {
              cursor: pointer;
              background-color: var(--slightBlue);
            }
          }
        }

        &:hover {
          background-color: var(--light);
        }

        h2,
        h3 {
          color: var(--dark);
          
          &:hover {
            cursor: pointer;
          }
        }

        h2 {
          font-size: calc(var(--h1) * 0.8);
          line-height: var(--h1);
        }

        h3 {
          font-size: calc(var(--h2) * 0.4);
          line-height: var(--h2);
        }

        .image-upload {
          display: block;
          width: 100%;
          height: 100%;

          position: absolute;
          top: 0;
          left: 0;

          opacity: 0;

          &:hover {
            cursor: pointer;
          }
        }
      }
    }
  }

  .insert-link-popup {
    .insert-link {
      --insertLinkWidth: 20vw;
    }
  }

  .display {
    box-sizing: border-box;
    width: @iw;
    min-height: 860px;
    margin: 30px auto;
    background-color: white;
    padding: 30px 60px;

    .title {
      box-sizing: border-box;
      display: block;
      width: 100%;
      height: 70px;
      line-height: 70px;
      font-size: 28px;
      padding-left: 28px;
      border-bottom: 1px solid var(--gray);
    }

    // .content {
    //   box-sizing: border-box;
    //   width: 100%;
    //   height: 800px;
    //   padding-top: 25px;
    //   outline: none;
    //   line-height: 60px;
    //   font-size: 21px;
    //   text-align: left;
    //   white-space: pre-wrap;
    // }
    .main {
      width: 100%;
    }
  }
}
</style>